package com.anduinslegacy.armory;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class PageGenerator {
	private InputStream in;
	private final String LINKTEXT = "Click here to see this characters achievements page.";
	private int point_limit;
	private static final Logger log = Logger.getLogger(PageGenerator.class
			.getName());

	public String getPageFor(int limit, String _guild) throws SAXException,
			IOException, ParserConfigurationException {
		this.point_limit = limit;
		in = fetchDataFor(_guild);
		if (in != null) {
			String[][] page = generatePage();
			return PrintSimpleList(page).toString();
		} else {
			// try again, sometimes the armory doesn't respond right away.
			in = fetchDataFor(_guild);
			if (in != null) {
				String[][] page = generatePage();
				return PrintSimpleList(page).toString();
			} else {
				return "Can not generate page without data from Armory!<p>Please try again later.";
			}
		}
	}

	public String getPageFor(String _guild, String toon) throws SAXException,
			IOException, ParserConfigurationException {
		System.out.println("at top of getPageFor()");
		in = fetchDataFor(_guild, toon);
		/*
		 * if (in != null) { String[][] page = generatePage(); return
		 * PrintSimpleList(page).toString(); } else { // try again, sometimes
		 * the armory doesn't respond right away. in = fetchDataFor(_guild); if
		 * (in != null) { String[][] page = generatePage(); return
		 * PrintSimpleList(page).toString(); } else { return
		 * "Can not generate page without data from Armory!<p>Please try again later."
		 * ; } }
		 */
		System.out.println("returning from getPageFor()");
		return "";
	}

	public String getSectionFor(int limit, String _guild) throws SAXException,
			IOException, ParserConfigurationException {
		this.point_limit = limit;
		in = fetchDataFor(_guild);
		if (in != null) {
			return printArray(generatePage()).toString();
		} else {
			// try again, sometimes the armory doesn't respond right away.
			in = fetchDataFor(_guild);
			if (in != null) {
				return printArray(generatePage()).toString();
			} else {
				return "Can not generate page without data from Armory!<p>Please try again later.";
			}
		}
	}
	
	public String getTopTen(int limit, String _guild) throws SAXException, IOException, ParserConfigurationException {
		this.point_limit = limit;
		in = fetchDataFor(_guild);
		if (in != null) {
			return PrintLimitedList(generatePage()).toString();
		} else {
			// try again, sometimes the armory doesn't respond right away.
			in = fetchDataFor(_guild);
			if (in != null) {
				return PrintLimitedList(generatePage()).toString();
			} else {
				return "Can not generate page without data from Armory!<p>Please try again later.";
			}
		}
	}

	/* Package private for testing purposes only */
	InputStream fetchData(int limit) {
		this.point_limit = limit;
		return fetchDataFor("Anduins+Legacy");
	}

	private InputStream fetchDataFor(String _guild) {

		// Define the parts of the URL
		//http://us.battle.net/wow/en/guild/aggramar/anduins%20legacy/roster
		String baseURL = "http://www.wowarmory.com/";
		String page = "guild-info";
		// String page = "character-statistics";
		String realm = "Aggramar";
		String character = "Woadrood";
		String guild = _guild;
		String address = baseURL + page + ".xml?r=" + realm + "&cn=" + character
				+ "&gn=" + guild;

		// Create the Objects we need for this.
		InputStream _stream = null;
		HttpURLConnection conn = null;
		URL url = null;

		try {
			url = new URL(address);
			conn = (HttpURLConnection) url.openConnection();
			conn
					.setRequestProperty(
							"User-Agent",
							"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");
			_stream = conn.getInputStream();
		} catch (MalformedURLException MURLE) {
			log.warning("FetchData() has thrown a MalformedURLException");
		} catch (IOException IOE) {
			log.warning("FetchData() has thrown a IOException");
		}
		return _stream;
	}

	private InputStream fetchDataFor(String _guild, String toon) {
		// Define the parts of the URL
		String baseURL = "http://www.wowarmory.com/";

		String page = "character-statistics";
		String realm = "Aggramar";
		String character = toon;

		String address = baseURL + page + ".xml?r=" + realm + "&n=" + character;

		// Create the Objects we need for this.
		InputStream _stream = null;
		HttpURLConnection conn = null;
		URL url = null;

		try {
			url = new URL(address);
			conn = (HttpURLConnection) url.openConnection();
			conn
					.setRequestProperty(
							"User-Agent",
							"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");
			_stream = conn.getInputStream();
		} catch (MalformedURLException MURLE) {
			log.warning("FetchData() has thrown a MalformedURLException");
		} catch (IOException IOE) {
			log.warning("FetchData() has thrown a IOException");
		}
		return _stream;
	}

	/* Package private for testing purposes only */
	String[][] generatePage() throws SAXException, IOException,
			ParserConfigurationException {

		// Get the document object created from the InputStream.
		Document doc = getDoc();

		// Create a list of "character" nodes.
		NodeList listOfCharacters = doc.getElementsByTagName("character");

		// Create an two dimensional array to hold the names/points.
		String[][] toons = new String[listOfCharacters.getLength()][3];

		// Loop through the list of characters (zero based array)
		for (int s = 0; s < listOfCharacters.getLength(); s++) {
			// Pull the first character out of the list of nodes.
			Node character = listOfCharacters.item(s);
			// Make sure we have a character node.
			if (character.getNodeType() == Node.ELEMENT_NODE) {
				// Pull the characters name into a local variable.
				String cName = character.getAttributes().getNamedItem("name").toString();
				// Strip off the unwanted values.
				cName = cName.substring((cName.indexOf("=") + 2), cName.length() - 1);

				// Pull the characters points into a local variable.
				String cPoints = character.getAttributes().getNamedItem("achPoints").toString();
				// Strip off the unwanted values.
				cPoints = cPoints.substring((cPoints.indexOf("=") + 2), cPoints.length() - 1);

				// Pull the characters level into a local variable.
				String cLevel = character.getAttributes().getNamedItem("level").toString();
				// Strip off the unwanted values.
				cLevel = cLevel.substring((cLevel.indexOf("=") + 2), cLevel.length() - 1);

				// Set the information in the first slot in the array.
				
				toons[s][0] = cPoints;
				toons[s][1] = cName;
				toons[s][2] = cLevel;

				//persist(cName, Integer.parseInt(cPoints));
			}// end of if statement
		}// end of for loop with s variable

		// Sort the array by points in descending order.
		Arrays.sort(toons, Collections.reverseOrder(new PointsComparator()));

		// Pass the completed array to printArray to get the finished page.
		return toons;
	}

	@SuppressWarnings("unused")
	private void persist(String name, int points) {
		CharacterFactory.create(name, points);
	}

	/**
	 * @return
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 */
	private Document getDoc() throws ParserConfigurationException,
			SAXException, IOException {
		DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
		Document doc = docBuilder.parse(in);

		// normalize text representation
		doc.getDocumentElement().normalize();
		return doc;
	}

	private StringBuffer printArray(String[][] array) {
		// Define local variables
		StringBuffer page = new StringBuffer();
		int x = 1;
		int currentPointLevel = 0;
		int userPoints = 0;
		String header = "";
		String cap = "";
		boolean headerWritten = false;
		String top = "<div class='post'><div class='timestamp'><a href='#'>Top</a></div>";
		String bottom = "</p></div></div>";

		// Row Loop
		for (int i = 0; i < array.length; i++) {
			// ****************************************
			if (headerWritten == false) {
				page.append(top);
				cap = array[i][0].substring(0, 1);
				if (cap.equals("9")) {
					currentPointLevel = 9000;
					header = "<h1><a name='9K' onclick=\"switchMenu('9K');\">9000 point achievers</a></h1><div class='post_body' id=\"9K\"><p>";
				}
				if (cap.equals("8")) {
					currentPointLevel = 8000;
					header = "<h1><a name='8K'>8000 point achievers</a></h1><div class='post_body'><p>";
				}
				if (cap.equals("7")) {
					currentPointLevel = 7000;
					header = "<h1><a name='7K'>7000 point achievers</a></h1><div class='post_body'><p>";
				}
				if (cap.equals("6")) {
					currentPointLevel = 6000;
					header = "<h1><a name='6K'>6000 point achievers</a></h1><div class='post_body'><p>";
				}
				if (cap.equals("5")) {
					currentPointLevel = 5000;
					header = "<h1><a name='5K'>5000 point achievers</a></h1><div class='post_body'><p>";
				}
				if (cap.equals("4")) {
					currentPointLevel = 4000;
					header = "<h1><a name='4K'>4000 point achievers</a></h1><div class='post_body'><p>";
				}
				if (cap.equals("3")) {
					currentPointLevel = 3000;
					header = "<h1><a name='3K'>3000 point achievers</a></h1><div class='post_body'><p>";
				}
				if (cap.equals("2")) {
					currentPointLevel = 2000;
					header = "<h1><a name='2K'>2000 point achievers</a></h1><div class='post_body'><p>";
				}
				if (cap.equals("1")) {
					currentPointLevel = 1000;
					header = "<h1><a name='1K'>1000 point achievers</a></h1><div class='post_body'><p>";
				}
				page.append("");
				page.append(header);
				headerWritten = true;
			} // End Set Header

			userPoints = Integer.parseInt(array[i][0]);
			if (userPoints >= currentPointLevel) {
				// Print the line number.
				page.append("<a STYLE='text-decoration:none' href='http://www.wowarmory.com/character-sheet.xml?r=Aggramar&cn=");
				page.append(array[i][1]);
				page.append("&gn=Anduins+Legacy'");
				page.append(">");
				page.append("<img src=../../images/icon_armory.png border='0' alt='Click to see character information'></a>&nbsp;");

				page.append("<a STYLE='text-decoration:none' href='http://www.wowjuju.com/RepCalc/");
				page.append(array[i][1]);
				page.append("'>");
				page.append("<img src=../../images/logo_left.gif border='0' alt='Click to see reputation info on wowjuju.com'></a>&nbsp;");
				page.append("[" + x + "]\t");

				// Print the points
				page.append("[" + array[i][0] + "]");

				// Print the level
				page.append("[" + array[i][2] + "] ");
				
				// Print the name
				page.append("<a href=http://www.wowarmory.com/character-achievements.xml?r=Aggramar&cn="
					+ array[i][1]
					+ "&gn=Anduins+Legacy title='"
					+ LINKTEXT + "'>" + array[i][1] + "</a>");

				// Advance to the next line.
				page.append("<br>");
				// Increase the line count by one.
				x++;
			} else {
				i--;
				headerWritten = false;
				page.append(bottom);
			}
			if (userPoints < point_limit) {
				break;
			}
		} // Row Loop
		return page;
	} // printArray


	private StringBuffer PrintSimpleList(String[][] array) {
		// Define local variables
		StringBuffer page = new StringBuffer();
		int x = 1;
		int userPoints = 0;

		// Row Loop
		for (int i = 0; i < array.length; i++) {
			userPoints = Integer.parseInt(array[i][0]);

			if (1000 > 0 && userPoints < 1000) {
				break;
			}

			page.append("<table border=0>");
			page.append("<tr><td width=25>&nbsp;</td><td>[" + x + "]\t");

			// Print the points
			page.append("[" + array[i][0] + "] ");

			// Print the name
			page
					.append("<a href=http://profiler.wowhead.com/?profile=us.aggramar."
							+ array[i][1] + ">" + array[i][1] + "</a>");

			// Advance to the next line.
			page.append("</td></tr>");

			// Increase the line count by one.
			x++;
		} // Row Loop
		page.append("</table>");
		return page;
	} // PrintSimpleList

	private StringBuffer PrintLimitedList(String[][] array) {
		// Define local variables
		StringBuffer page = new StringBuffer();
		int x = 1;
		int userPoints = 0;

		// Row Loop
		for (int i = 0; i < array.length; i++) {
			userPoints = Integer.parseInt(array[i][0]);

			if (point_limit > 0 && userPoints <= point_limit) {
				break;
			}

			page.append("<table border=0>");
			page.append("<tr><td width=25>&nbsp;</td><td>[" + x + "]\t");

			// Print the points
			page.append("[" + array[i][0] + "] ");

			// Print the name
			page
					.append("<a href=http://profiler.wowhead.com/?profile=us.aggramar."
							+ array[i][1] + ">" + array[i][1] + "</a>");

			// Advance to the next line.
			page.append("</td></tr>");

			// Increase the line count by one.
			x++;
		} // Row Loop
		page.append("</table>");
		return page;
	} // PrintLimitedList
	
	public String getXMLFor(int limit, String _guild) throws SAXException,
			IOException, ParserConfigurationException {
		this.point_limit = limit;
		in = fetchTestDataFor(_guild);
		StringBuffer sb = new StringBuffer();
		if (in != null) {
			Reader reader = new InputStreamReader(in);
			int data = reader.read();
			while (data != -1) {
				char theChar = (char) data;
				sb.append(theChar);
				data = reader.read();
			}

			reader.close();

			return sb.toString();// printArray(generatePage()).toString();
		} else {
			return "No Data";
		}
	}

	public String getXMLFor(String guild, String toon) throws SAXException,
			IOException, ParserConfigurationException {		
		in = fetchDataFor(guild,toon);
		StringBuffer sb = new StringBuffer();
		if (in != null) {
			Reader reader = new InputStreamReader(in);
			int data = reader.read();
			while (data != -1) {
				char theChar = (char) data;
				sb.append(theChar);
				data = reader.read();
			}

			reader.close();

			return sb.toString();// printArray(generatePage()).toString();
		} else {
			return "No Data";
		}
	}

	private InputStream fetchTestDataFor(String _guild) {
	
		// Define the parts of the URL
		//http://us.battle.net/wow/en/guild/aggramar/anduins%20legacy/roster
		String baseURL = "http://us.battle.net/wow/en/guild/";
		String page = "roster";
		// String page = "character-statistics";
		//String realm = "Aggramar";
		//String character = "Woadrood";
//		String guild = _guild;
		String address = baseURL + page;
//				+ "&gn=" + guild;
	
		// Create the Objects we need for this.
		InputStream _stream = null;
		HttpURLConnection conn = null;
		URL url = null;
	
		try {
			url = new URL(address);
			conn = (HttpURLConnection) url.openConnection();
			conn
					.setRequestProperty(
							"User-Agent",
							"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");
			_stream = conn.getInputStream();
		} catch (MalformedURLException MURLE) {
			log.warning("FetchData() has thrown a MalformedURLException");
		} catch (IOException IOE) {
			log.warning("FetchData() has thrown a IOException");
		}
		return _stream;
	}

}
